# -*- coding: utf-8 -*-
"""
管理员账户管理视图控制器

管理员用于管理所有用户账户、线下充值、余额调整和财务统计
支持批量操作和详细的财务报表生成
"""

from datetime import datetime, timedelta
from decimal import Decimal
from flask import Blueprint, render_template, request, jsonify, flash, redirect, url_for, current_app
from flask_login import login_required, current_user
from sqlalchemy import and_, or_, desc, func, text
from sqlalchemy.exc import SQLAlchemyError

from app import db
from app.controllers.account_controller import AccountController
from app.forms.account_forms import BalanceOperationForm, RechargeForm
from app.utils.decorators import admin_required
from app.utils.exceptions import BusinessError, ValidationError
from app.models.user import User
from app.models.account import UserAccount, Transaction

# 创建管理员账户管理蓝图
admin_accounts_bp = Blueprint('admin_accounts', __name__)


@admin_accounts_bp.route('/list')
@login_required
@admin_required
def list_accounts():
    """
    用户账户列表页面

    显示所有用户的账户信息，支持搜索、筛选和分页
    """
    # 获取查询参数
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    search = request.args.get('search', '').strip()
    status_filter = request.args.get('status', '')
    balance_filter = request.args.get('balance_filter', '')
    campus_filter = request.args.get('campus', '', type=int)

    try:
        # 构建查询
        query = db.session.query(
            User.id,
            User.username,
            User.real_name,
            User.phone,
            User.campus_id,
            UserAccount.balance,
            UserAccount.updated_at.label('account_updated_at')
        ).outerjoin(UserAccount, User.id == UserAccount.user_id)

        # 只查询学员账户
        query = query.filter(User.role == 'student')

        # 搜索条件
        if search:
            search_pattern = f'%{search}%'
            query = query.filter(
                or_(
                    User.username.like(search_pattern),
                    User.real_name.like(search_pattern),
                    User.phone.like(search_pattern)
                )
            )

        # 账户状态筛选已移除，因为数据库中user_accounts表无status字段

        # 余额筛选
        if balance_filter == 'zero':
            query = query.filter(or_(UserAccount.balance == 0, UserAccount.balance.is_(None)))
        elif balance_filter == 'low':
            query = query.filter(UserAccount.balance < 100)
        elif balance_filter == 'high':
            query = query.filter(UserAccount.balance > 1000)

        # 校区筛选
        if campus_filter:
            query = query.filter(User.campus_id == campus_filter)

        # 排序和分页
        query = query.order_by(desc(User.created_at))
        pagination = query.paginate(
            page=page, per_page=per_page, error_out=False
        )

        # 获取校区列表用于筛选
        from app.models.campus import Campus
        campuses = Campus.query.filter_by(status='active').all()

        # 计算统计数据
        stats = calculate_account_stats()

        return render_template(
            'admin_accounts/list.html',
            accounts=pagination.items,
            pagination=pagination,
            search=search,
            status_filter=status_filter,
            balance_filter=balance_filter,
            campus_filter=campus_filter,
            campuses=campuses,
            stats=stats,
            now=datetime.now,
            page_title='用户账户管理'
        )

    except SQLAlchemyError as e:
        current_app.logger.error(f"获取账户列表失败: {str(e)}")
        flash('获取账户列表失败，请稍后重试', 'error')
        return redirect(url_for('dashboard.index'))


@admin_accounts_bp.route('/detail/<int:user_id>')
@login_required
@admin_required
def account_detail(user_id):
    """
    用户账户详情页面

    显示指定用户的详细账户信息和操作选项
    """
    try:
        # 获取用户信息
        user = User.query.get_or_404(user_id)

        # 获取账户概览
        account_summary = AccountController.get_account_summary(user_id)

        # 获取最近交易记录
        recent_transactions = AccountController.get_transaction_history(
            user_id=user_id,
            page=1,
            per_page=10
        )

        # 获取消费统计
        monthly_stats = AccountController.get_consumption_statistics(
            user_id, period='month'
        )
        yearly_stats = AccountController.get_consumption_statistics(
            user_id, period='year'
        )

        # 创建操作表单
        operation_form = BalanceOperationForm()
        operation_form.user_id.data = user_id

        # 获取关联的预约信息
        from app.models.reservation import Reservation
        recent_reservations = Reservation.query.filter_by(
            student_id=user_id
        ).order_by(desc(Reservation.created_at)).limit(5).all()

        return render_template(
            'admin_accounts/detail.html',
            user=user,
            account_summary=account_summary,
            recent_transactions=recent_transactions['transactions'],
            recent_reservations=recent_reservations,
            monthly_stats=monthly_stats,
            yearly_stats=yearly_stats,
            operation_form=operation_form,
            page_title=f'{user.real_name or user.username} - 账户详情'
        )

    except BusinessError as e:
        flash(str(e), 'error')
        return redirect(url_for('admin_accounts.list_accounts'))
    except Exception as e:
        current_app.logger.error(f"获取账户详情失败 - 用户ID: {user_id}, 错误: {str(e)}")
        flash('获取账户详情失败，请稍后重试', 'error')
        return redirect(url_for('admin_accounts.list_accounts'))


@admin_accounts_bp.route('/recharge/<int:user_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def offline_recharge(user_id):
    """
    线下充值页面

    管理员为用户进行线下充值（现金、银行转账等）
    """
    try:
        # 获取用户信息
        user = User.query.get_or_404(user_id)

        # 获取账户信息
        account_summary = AccountController.get_account_summary(user_id)

        form = RechargeForm()

        # 修改支付方式选项为线下支付方式
        form.payment_method.choices = [
            ('cash', '现金支付'),
            ('bank_transfer', '银行转账'),
            ('pos', 'POS机刷卡'),
            ('other', '其他方式')
        ]

        if form.validate_on_submit():
            try:
                # 支付方式映射到数据库ENUM值
                payment_method_mapping = {
                    'cash': 'offline',
                    'bank_transfer': 'offline',
                    'pos': 'offline',
                    'other': 'offline',
                    'wechat': 'wechat',
                    'alipay': 'alipay'
                }

                db_payment_method = payment_method_mapping.get(form.payment_method.data, 'offline')

                # 记录管理员操作信息
                description = f"线下充值 - {form.payment_method.data} (操作员: {current_user.username})"
                if form.remarks.data:
                    description += f" - {form.remarks.data}"

                # 执行充值
                result = AccountController.recharge_account(
                    user_id=user_id,
                    amount=form.amount.data,
                    payment_method=db_payment_method,
                    payment_reference=f"OFFLINE_{datetime.now().strftime('%Y%m%d%H%M%S')}",
                    operator_id=current_user.id
                )

                if result['success']:
                    # 记录管理员操作日志
                    current_app.logger.info(
                        f"管理员线下充值 - 操作员: {current_user.username}, "
                        f"用户: {user.username}, 金额: {form.amount.data}, "
                        f"方式: {form.payment_method.data}"
                    )

                    flash(
                        f'线下充值成功！为用户 {user.real_name or user.username} '
                        f'充值 {form.amount.data} 元',
                        'success'
                    )
                    return redirect(url_for('admin_accounts.account_detail', user_id=user_id))
                else:
                    flash('充值失败，请稍后重试', 'error')

            except BusinessError as e:
                flash(str(e), 'error')
            except Exception as e:
                current_app.logger.error(f"线下充值失败 - 用户ID: {user_id}, 错误: {str(e)}")
                flash('充值失败，请稍后重试', 'error')

        return render_template(
            'admin_accounts/recharge.html',
            user=user,
            account_summary=account_summary,
            form=form,
            now=datetime.now,
            page_title=f'为 {user.real_name or user.username} 线下充值'
        )

    except Exception as e:
        current_app.logger.error(f"加载线下充值页面失败 - 用户ID: {user_id}, 错误: {str(e)}")
        flash('加载页面失败，请稍后重试', 'error')
        return redirect(url_for('admin_accounts.list_accounts'))


@admin_accounts_bp.route('/statistics')
@login_required
@admin_required
def financial_statistics():
    """
    财务统计页面

    显示全系统的财务统计数据和图表
    """
    # 获取查询参数
    period = request.args.get('period', 'month')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')

    try:
        # 计算统计数据
        stats = calculate_financial_statistics(period, start_date, end_date)

        return render_template(
            'admin_accounts/statistics.html',
            stats=stats,
            period=period,
            start_date=start_date,
            end_date=end_date,
            page_title='财务统计'
        )

    except Exception as e:
        current_app.logger.error(f"获取财务统计失败: {str(e)}")
        flash('获取财务统计失败，请稍后重试', 'error')
        return redirect(url_for('admin_accounts.list_accounts'))




# AJAX API 路由

@admin_accounts_bp.route('/api/balance-operation', methods=['POST'])
@login_required
@admin_required
def api_balance_operation():
    """
    余额操作 API

    处理管理员的余额调整操作
    """
    try:
        form = BalanceOperationForm()
        if form.validate_on_submit():
            user_id = int(form.user_id.data)
            operation_type = form.operation_type.data
            amount = form.amount.data
            reason = form.reason.data

            # 执行操作
            if operation_type == 'adjust':
                # 余额调整：将用户余额调整到指定金额
                success = adjust_user_balance(user_id, amount, reason)
                operation_name = '余额调整'
            elif operation_type == 'recharge':
                # 充值：在现有余额基础上增加
                try:
                    result = AccountController.recharge_account(
                        user_id=user_id,
                        amount=amount,
                        payment_method='offline',
                        operator_id=current_user.id
                    )
                    success = result.get('success', False)
                    operation_name = '余额充值'
                except Exception:
                    success = False
            elif operation_type == 'consume':
                # 扣减：从现有余额中扣除
                try:
                    result = AccountController.consume_balance(
                        user_id=user_id,
                        amount=amount,
                        description=f"管理员扣减 - {reason} (操作员: {current_user.username})"
                    )
                    success = result.get('success', False)
                    operation_name = '余额扣减'
                except Exception:
                    success = False
            else:
                return jsonify({
                    'success': False,
                    'error': '不支持的操作类型'
                }), 400

            if success:
                # 记录管理员操作日志
                user = User.query.get(user_id)
                current_app.logger.info(
                    f"管理员账户操作 - 操作员: {current_user.username}, "
                    f"用户: {user.username if user else user_id}, "
                    f"操作: {operation_name}, 金额: {amount}, 原因: {reason}"
                )

                return jsonify({
                    'success': True,
                    'message': f'{operation_name}操作成功'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': f'{operation_name}操作失败'
                }), 400

        else:
            errors = []
            for field, field_errors in form.errors.items():
                errors.extend(field_errors)
            return jsonify({
                'success': False,
                'error': '表单验证失败: ' + '; '.join(errors)
            }), 400

    except Exception as e:
        current_app.logger.error(f"余额操作API失败: {str(e)}")
        return jsonify({
            'success': False,
            'error': '操作失败，请稍后重试'
        }), 500


@admin_accounts_bp.route('/api/user-balance/<int:user_id>')
@login_required
@admin_required
def api_get_user_balance(user_id):
    """
    获取指定用户账户余额 API（管理员专用）

    返回JSON格式的指定用户账户余额信息
    """
    try:
        # 验证用户是否存在
        user = User.query.get(user_id)
        if not user:
            return jsonify({
                'success': False,
                'error': '用户不存在'
            }), 404

        # 校区管理员只能查看本校区用户
        if current_user.is_campus_admin() and user.campus_id != current_user.campus_id:
            return jsonify({
                'success': False,
                'error': '您只能查看本校区用户的账户信息'
            }), 403

        # 获取账户概览
        account_summary = AccountController.get_account_summary(user_id)

        return jsonify({
            'success': True,
            'data': {
                'balance': float(account_summary['balance']),
                'available_balance': float(account_summary['available_balance']),
                'user_id': user_id,
                'username': user.username,
                'real_name': user.real_name
            }
        })

    except BusinessError as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 400
    except Exception as e:
        current_app.logger.error(f"获取用户余额API失败 - 用户ID: {user_id}, 错误: {str(e)}")
        return jsonify({
            'success': False,
            'error': '获取余额失败'
        }), 500


@admin_accounts_bp.route('/api/export-financial-data')
@login_required
@admin_required
def api_export_financial_data():
    """
    导出财务数据 API

    支持导出 Excel 和 CSV 格式的财务数据
    """
    try:
        # 获取参数
        period = request.args.get('period', 'month')
        start_date = request.args.get('start_date')
        end_date = request.args.get('end_date')
        export_format = request.args.get('format', 'excel')

        # 计算统计数据
        stats = calculate_financial_statistics(period, start_date, end_date)

        # 这里应该实现实际的导出逻辑
        # 目前返回一个模拟的响应
        return jsonify({
            'success': True,
            'message': f'财务数据({export_format.upper()})导出功能开发中...',
            'download_url': '#'
        })

    except Exception as e:
        current_app.logger.error(f"导出财务数据失败: {str(e)}")
        return jsonify({
            'success': False,
            'error': '导出失败，请稍后重试'
        }), 500




# 辅助函数

def calculate_account_stats():
    """计算账户统计数据"""
    try:
        stats = {}

        # 总用户数
        stats['total_users'] = User.query.filter_by(role='student').count()

        # 开通账户用户数
        stats['active_accounts'] = db.session.query(UserAccount).join(User).filter(
            User.role == 'student'
        ).count()

        # 总余额
        result = db.session.query(func.sum(UserAccount.balance)).join(User).filter(
            User.role == 'student'
        ).scalar()
        stats['total_balance'] = float(result) if result else 0.0


        # 今日充值
        today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        result = db.session.query(func.sum(Transaction.amount)).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.type == 'recharge',
            Transaction.created_at >= today
        ).scalar()
        stats['today_recharge'] = float(result) if result else 0.0

        # 今日消费
        result = db.session.query(func.sum(Transaction.amount)).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.type == 'consume',
            Transaction.created_at >= today
        ).scalar()
        stats['today_consumption'] = float(abs(result)) if result else 0.0

        return stats

    except Exception as e:
        current_app.logger.error(f"计算账户统计失败: {str(e)}")
        return {}




def adjust_user_balance(user_id, target_balance, reason):
    """调整用户余额到指定金额"""
    try:
        # 获取当前账户信息
        account = UserAccount.query.filter_by(user_id=user_id).first()
        if not account:
            # 如果账户不存在，创建新账户
            account = UserAccount(
                user_id=user_id,
                balance=Decimal('0')
            )
            db.session.add(account)
            db.session.flush()  # 确保账户创建

        # 计算调整金额
        old_balance = account.balance
        adjustment_amount = target_balance - old_balance

        # 如果调整金额为0，无需操作
        if adjustment_amount == 0:
            return True

        # 更新余额
        account.balance = target_balance

        # 根据调整方向选择交易类型
        if adjustment_amount > 0:
            transaction_type = 'recharge'
            transaction_amount = adjustment_amount
        else:
            transaction_type = 'consume'
            transaction_amount = adjustment_amount  # 保持负数，与consume逻辑一致

        # 创建交易记录
        transaction = Transaction(
            user_id=user_id,
            type=transaction_type,
            amount=transaction_amount,
            balance_after=target_balance,
            description=f"管理员余额调整 - {reason} (操作员: {current_user.username})",
            operator_id=current_user.id
        )

        db.session.add(transaction)
        db.session.commit()

        current_app.logger.info(
            f"管理员余额调整成功 - 操作员: {current_user.username}, "
            f"用户ID: {user_id}, 原余额: {old_balance}, "
            f"新余额: {target_balance}, 调整金额: {adjustment_amount}, 原因: {reason}"
        )

        return True

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"调整用户余额失败 - 用户ID: {user_id}, 错误: {str(e)}")
        return False


def calculate_financial_statistics(period, start_date=None, end_date=None):
    """计算财务统计数据"""
    try:
        from datetime import datetime, timedelta

        # 确定时间范围
        now = datetime.now()
        if start_date and end_date:
            # 自定义日期范围
            start_datetime = datetime.strptime(start_date, '%Y-%m-%d')
            end_datetime = datetime.strptime(end_date, '%Y-%m-%d').replace(hour=23, minute=59, second=59)
        else:
            # 预设周期
            if period == 'week':
                start_datetime = now - timedelta(days=7)
            elif period == 'month':
                start_datetime = now - timedelta(days=30)
            elif period == 'quarter':
                start_datetime = now - timedelta(days=90)
            elif period == 'year':
                start_datetime = now - timedelta(days=365)
            else:
                start_datetime = now - timedelta(days=30)
            end_datetime = now

        # 查询统计数据
        stats = {}

        # 总交易统计
        total_transactions = db.session.query(func.count(Transaction.id)).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.created_at >= start_datetime,
            Transaction.created_at <= end_datetime
        ).scalar() or 0

        # 充值统计
        recharge_result = db.session.query(
            func.count(Transaction.id),
            func.sum(Transaction.amount)
        ).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.type == 'recharge',
            Transaction.created_at >= start_datetime,
            Transaction.created_at <= end_datetime
        ).first()

        recharge_count = recharge_result[0] or 0
        total_recharge = float(recharge_result[1] or 0)

        # 消费统计
        consume_result = db.session.query(
            func.count(Transaction.id),
            func.sum(Transaction.amount)
        ).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.type == 'consume',
            Transaction.created_at >= start_datetime,
            Transaction.created_at <= end_datetime
        ).first()

        consume_count = consume_result[0] or 0
        total_consume = float(abs(consume_result[1] or 0))

        # 退款统计
        refund_result = db.session.query(
            func.count(Transaction.id),
            func.sum(Transaction.amount)
        ).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.type == 'refund',
            Transaction.created_at >= start_datetime,
            Transaction.created_at <= end_datetime
        ).first()

        refund_count = refund_result[0] or 0
        total_refund = float(refund_result[1] or 0)

        # 按日期分组的交易统计（用于图表）
        daily_stats = {}
        transactions = db.session.query(
            func.date(Transaction.created_at).label('date'),
            Transaction.type,
            func.sum(Transaction.amount).label('amount')
        ).join(User, Transaction.user_id == User.id).filter(
            User.role == 'student',
            Transaction.created_at >= start_datetime,
            Transaction.created_at <= end_datetime
        ).group_by(
            func.date(Transaction.created_at),
            Transaction.type
        ).all()

        for trans in transactions:
            date_str = trans.date.strftime('%Y-%m-%d')
            if date_str not in daily_stats:
                daily_stats[date_str] = {'recharge': 0, 'consume': 0, 'refund': 0}
            daily_stats[date_str][trans.type] = float(abs(trans.amount))

        stats.update({
            'period': period,
            'start_date': start_datetime.strftime('%Y-%m-%d'),
            'end_date': end_datetime.strftime('%Y-%m-%d'),
            'total_transactions': total_transactions,
            'recharge_count': recharge_count,
            'total_recharge': total_recharge,
            'consume_count': consume_count,
            'total_consume': total_consume,
            'refund_count': refund_count,
            'total_refund': total_refund,
            'net_income': total_recharge - total_consume + total_refund,
            'daily_stats': daily_stats
        })

        return stats

    except Exception as e:
        current_app.logger.error(f"计算财务统计失败: {str(e)}")
        return {}